home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * candraw -
- * Draw points, lines, rectangles and texture maps onto a
- * canvas.
- *
- * Paul Haeberli - 1991
- *
- * exports
- *
- void setalphascale(s)
- void setalpha(a)
- void drawapoint(c,x,y)
- void drawaaline(c,x1,y1,x2,y2)
- void canbeginscan(c,supersample);
- void canvertex(x,y);
- void cannextfacet();
- void canendscan();
- *
- */
- #include "values.h"
- #include "math.h"
- #include "canvas.h"
- #include "texture.h"
- #include "izoom.h"
- #include "polyscan.h"
-
- #define LINETABSIZE (100)
-
- float can_curalpha = 1.0;
- float can_curalphascale = 1.0;
- static unsigned char *linetab;
- static canvas *curcanvas;
- static TEXTURE *curtm;
- static vect curedgex, curedgey;
- static float sminx, smaxx;
- static float sminy, smaxy;
- static int dosupersample;
- static int doscanclip;
- static unsigned char *rowbuf;
- static int rowbufx, rowbuflen, curputy, lasty;
- static int aaxmin, aaxmax, curialph;
-
- #define SUPERSAMPLES (4)
-
- void setalphascale(s)
- float s;
- {
- can_curalphascale = s;
- }
-
- void setalpha(a)
- float a;
- {
- can_curalpha = a;
- }
-
- static void initlinetab()
- {
- int i, i3, a, b, c;
- float pos, dscale;
-
- setfiltertype(TRIANGLE);
- dscale = 1.0/filterinteg(0.0-0.5,0.0+0.5,1.0);
- linetab = (unsigned char *)mymalloc(3*LINETABSIZE);
- i3 = 0;
- for(i=0; i<LINETABSIZE; i++) {
- pos = i/(LINETABSIZE-1.0);
- a = round(255.0*dscale*filterinteg(pos-2.0,pos-1.0,1.0));
- b = round(255.0*dscale*filterinteg(pos-1.0,pos+0.0,1.0));
- c = round(255.0*dscale*filterinteg(pos+0.0,pos+1.0,1.0));
- linetab[i3+2] = a;
- linetab[i3+1] = b;
- linetab[i3+0] = c;
- i3 += 3;
- }
- }
-
- /*
- * drawpoint -
- * draw an antialiased point at the specified position
- * with the current color and alpha
- *
- */
- void drawapoint(c,x,y)
- canvas *c;
- float x, y;
- {
- float fx, fy;
- int doclip;
- short ix, iy, a;
- unsigned long *d;
- rct brect;
- unsigned char abuf[2];
-
- if(!blendrow)
- setblend(BLEND_RGB);
- ix = ffloor(x);
- iy = ffloor(y);
- if(ix<0 || iy<0 || ix>=c->xsize-2 || iy>=c->ysize-2)
- doclip = 1;
- else
- doclip = 0;
- fx = x-ix;
- fy = y-iy;
- a = 255.0*can_curalpha*can_curalphascale;
- brect.xmin = ix;
- brect.xmax = ix+1;
- brect.ymin = iy;
- brect.ymax = iy+1;
- saverect(c,&brect);
- abuf[0] = (a*(1.0-fx)*(1.0-fy));
- abuf[1] = (a*fx*(1.0-fy));
- blendrow(c,abuf,ix,iy,2,doclip);
- abuf[0] = (a*(1.0-fx)*fy);
- abuf[1] = (a*fx*fy);
- blendrow(c,abuf,ix,iy+1,2,doclip);
- markdirty(c,&brect,1);
- }
-
- static int nearedge(c,x,y)
- canvas *c;
- float x, y;
- {
- if(x<2 || y<2)
- return 1;
- if(x>c->xsize-3 || y>c->ysize-3)
- return 1;
- return 0;
- }
-
- void drawaaline(c,x1,y1,x2,y2)
- canvas *c;
- float x1,y1,x2,y2;
- {
- float dx, dy, temp;
- float xmin, xmax, ymin, ymax, fy, dfy;
- int xs, xf, iy;
- short a;
- unsigned long *data;
- unsigned char *wptr;
- rct brect;
- int doclip;
- unsigned char abuf[3];
-
- if(nearedge(c,x1,y1) || nearedge(c,x2,y2))
- doclip = 1;
- else
- doclip = 0;
- if(!linetab)
- initlinetab();
- if(!blendrow)
- setblend(BLEND_RGB);
- a = 256.0*can_curalpha*can_curalphascale;
- dx = x2-x1;
- if(dx<0.0) {
- xmin = x2;
- xmax = x1;
- dx = -dx;
- } else {
- xmin = x1;
- xmax = x2;
- }
- dy = y2-y1;
- if(dy<0.0) {
- ymin = y2;
- ymax = y1;
- dy = -dy;
- } else {
- ymin = y1;
- ymax = y2;
- }
- if(dx<0.01 && dy<0.01)
- return;
- brect.xmin = xmin-1;
- brect.xmax = xmax+1;
- brect.ymin = ymin-1;
- brect.ymax = ymax+1;
- saverect(c,&brect);
- if(dx>dy) { /* sorta horizonal line */
- if(x1>x2) {
- temp = x1;
- x1 = x2;
- x2 = temp;
- temp = y1;
- y1 = y2;
- y2 = temp;
- }
- xs = ffloor(x1+0.5);
- xf = ffloor(x2+0.5);
- dfy = (y2-y1)/(x2-x1);
- fy = y1+(x1-xs)*dfy;
- data = c->data;
- while(xs<=xf) {
- iy = ffloor(fy);
- wptr = linetab+(3*(int)((LINETABSIZE-1)*(fy-iy)));
- abuf[0] = (a*wptr[0])>>8;
- abuf[1] = (a*wptr[1])>>8;
- abuf[2] = (a*wptr[2])>>8;
- blendcol(c,abuf,xs,iy,3,doclip);
- fy += dfy;
- xs++;
- }
- } else { /* sorta vertical line */
- if(y1>y2) {
- temp = y1;
- y1 = y2;
- y2 = temp;
- temp = x1;
- x1 = x2;
- x2 = temp;
- }
- xs = ffloor(y1+0.5);
- xf = ffloor(y2+0.5);
- dfy = (x2-x1)/(y2-y1);
- fy = x1+(y1-xs)*dfy;
- data = c->data;
- while(xs<=xf) {
- iy = ffloor(fy);
- wptr = linetab+(3*(int)((LINETABSIZE-1)*(fy-iy)));
- abuf[0] = (a*wptr[0])>>8;
- abuf[1] = (a*wptr[1])>>8;
- abuf[2] = (a*wptr[2])>>8;
- blendrow(c,abuf,iy,xs,3,doclip);
- fy += dfy;
- xs++;
- }
- }
- markdirty(c,&brect,1);
- }
-
- static gettmpos(pos,tp)
- vect *pos, *tp;
- {
- tp->x = pos->x*curedgex.x+pos->y*curedgex.y+curedgex.z;
- tp->y = pos->x*curedgey.x+pos->y*curedgey.y+curedgey.z;
- }
-
- static void putaarow()
- {
- int len, n;
- unsigned char *buf;
-
- if(aaxmin != MAXINT) {
- len = aaxmax-aaxmin+1;
- buf = rowbuf+aaxmin;
- n = len;
- while(n--) {
- *buf = (curialph*(*buf))/(SUPERSAMPLES*SUPERSAMPLES);
- buf++;
- }
- blendrow(curcanvas,rowbuf+aaxmin,rowbufx+aaxmin,curputy,len,doscanclip);
- }
- }
-
- static void initaarow()
- {
- bzero(rowbuf,rowbuflen);
- aaxmin = MAXINT;
- aaxmax = -MAXINT;
- }
-
- static void fillaarow(y,x1,x2)
- int y, x1, x2;
- {
- int sx1, sx2, n;
- unsigned char *cptr;
-
- if(y<0)
- return;
- while(lasty<y) {
- if((lasty%SUPERSAMPLES) == 0) {
- curputy = lasty/SUPERSAMPLES;
- if(aaxmin != MAXINT) {
- putaarow();
- bzero(rowbuf+aaxmin,aaxmax-aaxmin+1);
- aaxmin = MAXINT;
- aaxmax = -MAXINT;
- curputy++;
- }
- }
- lasty++;
- }
- lasty = y;
- sx1 = (x1/SUPERSAMPLES)-rowbufx;
- sx2 = (x2/SUPERSAMPLES)-rowbufx;
- if(aaxmin>sx1)
- aaxmin=sx1;
- if(aaxmax<sx2)
- aaxmax=sx2;
- if(sx1 == sx2) {
- rowbuf[sx1] += x2-x1+1;
- } else {
- rowbuf[sx1] += SUPERSAMPLES-(x1%SUPERSAMPLES);
- rowbuf[sx2] += 1+(x2%SUPERSAMPLES);
- n = sx2-sx1-1;
- cptr = rowbuf+sx1+1;
- while(n) {
- if(n>=4) {
- cptr[0] += SUPERSAMPLES;
- cptr[1] += SUPERSAMPLES;
- cptr[2] += SUPERSAMPLES;
- cptr[3] += SUPERSAMPLES;
- cptr += 4;
- n -= 4;
- } else {
- *cptr++ += SUPERSAMPLES;
- n--;
- }
- }
- }
- }
-
- void cantm(tm,edgex,edgey)
- TEXTURE *tm;
- vect *edgex, *edgey;
- {
- curtm = tm;
- if(tm) {
- curedgex = *edgex;
- curedgey = *edgey;
- }
- }
-
- static void out_span(int y, int x1, int x2)
- {
- int n, nn, a;
- unsigned char *t;
- vect pos, tp, c;
- double ftmx, ftmy, dtmx, dtmy;
- int x, tmxsize;
- unsigned char *rptr;
-
- n = x2-x1+1;
- if(curtm) {
- t = curtm->data[0];
- tmxsize = curtm->xsize;
- pos.x = x1;
- pos.y = y;
- gettmpos(&pos,&tp);
- ftmx = tp.x;
- ftmy = tp.y;
- dtmx = curedgex.x;
- dtmy = curedgey.x;
- nn = n;
- rptr = rowbuf;
- while(nn--) {
- *rptr++ = (curialph*t[((int)ftmy)*tmxsize+((int)ftmx)])>>8;
- ftmx += dtmx;
- ftmy += dtmy;
- }
- blendrow(curcanvas,rowbuf,x1,y,n,doscanclip);
- } else {
- if(dosupersample)
- fillaarow(y,x1,x2);
- else
- constblendrow(curcanvas,curialph,x1,y,n,doscanclip);
- }
- }
-
- void canbeginscan(c,supersample)
- canvas *c;
- int supersample;
- {
- if(!blendrow)
- setblend(BLEND_RGB);
- if(curtm)
- dosupersample = 0;
- else
- dosupersample = supersample;
- curcanvas = c;
- doscanclip = 0;
- sminx = sminy = MAXFLOAT;
- smaxx = smaxy = -MAXFLOAT;
- lasty = -100000;
- scanoutspan(out_span);
- scanbeginscan();
- }
-
- canvertex(x,y)
- float x, y;
- {
- if(nearedge(curcanvas,x,y))
- doscanclip = 1;
- if(dosupersample)
- scanvertex(x*SUPERSAMPLES,y*SUPERSAMPLES);
- else
- scanvertex(x,y);
- if(sminx>x) sminx = x;
- if(sminy>y) sminy = y;
- if(smaxx<x) smaxx = x;
- if(smaxy<y) smaxy = y;
- }
-
- void cannextfacet()
- {
- scanendfacet();
- scanbeginfacet();
- }
-
- void canendscan()
- {
- rct brect;
- int npix;
-
- if(sminx==MAXFLOAT)
- return;
- npix = smaxx-sminx+4;
- rowbuf = (unsigned char *)bufalloc(rowbuf,npix);
- rowbufx = sminx-2;
- rowbuflen = npix;
- curialph = ffloor((255.0*can_curalpha*can_curalphascale)+0.49);
- brect.xmin = sminx-1;
- brect.xmax = smaxx+1;
- brect.ymin = sminy-1;
- brect.ymax = smaxy+1;
- saverect(curcanvas,&brect);
- if(dosupersample) {
- initaarow();
- scanendscan();
- putaarow();
- } else {
- scanendscan();
- }
- markdirty(curcanvas,&brect,1);
- }
-